import { ModalsDemos } from "@/lib/@docs/demos/src";
import { Layout } from "@/layout";
import { MDX_DATA } from "@/mdx";

export default Layout(MDX_DATA.Modals);

## Installation

<InstallScript packages="@mantine/modals" />

## Setup ModalsProvider

Wrap your app with `ModalsProvider` component:

```tsx
import { MantineProvider } from "@mantine/core";
import { ModalsProvider } from "@mantine/modals";

function Demo() {
  return (
    <MantineProvider>
      <ModalsProvider>{/* Your app here */}</ModalsProvider>
    </MantineProvider>
  );
}
```

## Confirm modal

@mantine/modals package includes special modal that can be used for confirmations.
Component includes confirm and cancel buttons and supports children to display additional
information about action. Use `openConfirmModal` function to open a confirm modal:

<Demo data={ModalsDemos.confirm} />

`openConfirmModal` function accepts one argument with following properties:

- `modalId` – modal id, defaults to random id, can be used to close modal programmatically
- `children` – additional modal content displayed before actions
- `onCancel` – called when cancel button is clicked
- `onConfirm` – called when confirm button is clicked
- `closeOnConfirm` – should modal be closed when confirm button is clicked, defaults to `true`
- `closeOnCancel` – should modal be closed when cancel button is clicked, defaults to `true`
- `cancelProps` – cancel button props
- `confirmProps` – confirm button props
- `groupProps` – buttons [Group](/core/group/) props
- `labels` – cancel and confirm buttons labels, can be defined on ModalsProvider

Using this properties you can customize confirm modal to match current context requirements:

<Demo data={ModalsDemos.confirmCustomize} />

To setup shared labels for confirm modals set `labels` on `ModalsProvider`:

```tsx
import { ModalsProvider } from "@mantine/modals";

function Demo() {
  return (
    <ModalsProvider labels={{ confirm: "Submit", cancel: "Cancel" }}>
      {/* Your app here */}
    </ModalsProvider>
  );
}
```

## Context modals

You can define any amount of modals in ModalsProvider context:

```tsx
import { Button, Text } from "@mantine/core";
import { ContextModalProps, ModalsProvider } from "@mantine/modals";

const TestModal = ({
  context,
  id,
  innerProps,
}: ContextModalProps<{ modalBody: string }>) => (
  <>
    <Text size="sm">{innerProps.modalBody}</Text>
    <Button fullWidth mt="md" onClick={() => context.closeModal(id)}>
      Close modal
    </Button>
  </>
);

function Demo() {
  return (
    <ModalsProvider modals={{ demonstration: TestModal /* ...other modals */ }}>
      {/* Your app here */}
    </ModalsProvider>
  );
}
```

And then open one of these modals with `modals.openContextModal` function.
`modals.openContextModal` function accepts 2 arguments: modal key (should match one defined on ModalsProvider) and modal props:

<Demo data={ModalsDemos.context} />

## Typesafe context modals

By default `innerProps` and `modal` are not typesafe. You can add typesafety with a Typescript module declaration.

```tsx
const TestModal = ({
  context,
  id,
  innerProps,
}: ContextModalProps<{ modalBody: string }>) => (
  <>
    <Text size="sm">{innerProps.modalBody}</Text>
    <Button fullWidth mt="md" onClick={() => context.closeModal(id)}>
      Close modal
    </Button>
  </>
);
const modals = {
  demonstration: TestModal,
  /* ...other modals */
};
declare module "@mantine/modals" {
  export interface MantineModalsOverride {
    modals: typeof modals;
  }
}
function Demo() {
  return <ModalsProvider modals={modals}>{/* Your app here */}</ModalsProvider>;
}
```

Typesafe context modals will force you to use the correct types for `openContextModal`:

```tsx
import { closeModal, openContextModal } from "@mantine/modals";

openContextModal({
  modal: "demonstration",
  title: "Test modal from context",
  innerProps: {
    modalBody:
      "This modal was defined in ModalsProvider, you can open it anywhere in you app with useModals hook",
  },
});
closeModal("demonstration");
```

## Content modals

With `modals.open` function you can open a modal with any content:

<Demo data={ModalsDemos.content} />

## Multiple opened modals

You can open multiple layers of modals. Every opened modal is added as first element in modals queue.
To close all opened modals call `modals.closeAll()` function:

<Demo data={ModalsDemos.multipleSteps} />

## Modal props

You can pass props down to the [Modal](/core/modal) component by adding them to the
argument of every `modals.x` function. Example of setting `radius`, `size` and `withCloseButton`
props:

<Demo data={ModalsDemos.modalProps} />

## Dynamic Content and the modals manager

Note that when using the Modals manager, dynamic content is not supported.
Once modal is opened, a snapshot is saved into internal state and cannot be updated.

If you intend to have dynamic content in modals, either:

- Use internal component state, or
- Use the modal component instead of modals manager
